﻿using System;
using Microsoft.Xna.Framework;

namespace MaterialEditor
{
    public class LerpNode : Node
    {
        private InputSlot A
        {
            get { return input[0]; }
        }
        private InputSlot B
        {
            get { return input[1]; }
        }
        private InputSlot w
        {
            get { return input[2]; }
        }

        private NodeValueType[][] _acceptTypes;
        public override NodeValueType[][] acceptTypes
        {
            get { return _acceptTypes; }
        }

        public LerpNode(int x, int y)
            : base(x, y)
        {
            input = new InputSlot[]
            {
                new InputSlot(this, null, "A"),
                new InputSlot(this, null, "B"),
                new InputSlot(this, null, "w"),
            };

            output = new InputSlot(this, null, "");

            Name = "Interpolate";

            _acceptTypes = new NodeValueType[][]
            {
                new NodeValueType[] { NodeValueType.ValueColor, NodeValueType.ValueFloat, NodeValueType.ValueTexture, NodeValueType.ValueVector2, NodeValueType.ValueVector3 },
                new NodeValueType[] { NodeValueType.ValueColor, NodeValueType.ValueFloat, NodeValueType.ValueTexture, NodeValueType.ValueVector2, NodeValueType.ValueVector3 },
                new NodeValueType[] { NodeValueType.ValueFloat },
            };

            A.Connected += A_Connected;
            B.Connected += B_Connected;
            w.Connected += w_Connected;

            A.Disconnected += A_Disconnected;
            B.Disconnected += B_Disconnected;
            w.Disconnected += w_Disconnected;

            A.ValueChanged += A_Connected;
            B.ValueChanged += B_Connected;
            w.ValueChanged += w_Connected;
        }

        void w_Disconnected()
        {
            _result = null;
        }

        void B_Disconnected()
        {
            _result = null;
        }

        void A_Disconnected()
        {
            _result = null;
        }

        void w_Connected()
        {
            if (w.value.type != NodeValueType.ValueFloat)
            {
                w.connector.Disconnect();
                return;
            }

            A_Connected();
        }

        void B_Connected()
        {
            try
            {
                if (A.connector != null && w.connector != null)
                    _result = NodeValue.Lerp(A.value, B.value, (float)w.value.Value);
            }
            catch (InvalidOperationException e)
            {
                B.connector.Disconnect();
            }
        }

        void A_Connected()
        {
            try
            {
                if (B.connector != null && w.connector != null)
                    _result = NodeValue.Lerp(A.value, B.value, (float)w.value.Value);
            }
            catch (InvalidOperationException e)
            {
                A.connector.Disconnect();
            }
        }

        private NodeValue _result;
        public override NodeValue Result
        {
            get { return _result; }
        }

        public override object Clone()
        {
            LerpNode n = new LerpNode((int)position.X, (int)position.Y);
            if (Result != null)
                n._result = new NodeValue(_result.Value);

            return n;
        }
    }
}